package com.kfm.base.reflect;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.RandomAccess;

public class Demo {

    public static void main(String[] args) {
        // 1. 获取类的 class 对象
        // 类名.class
        Class<Student> studentClass = Student.class;
        // 对象.getClass()
//        Student student = new Student();
//
//        Class<? extends Student> aClass = student.getClass();

        try {
            // Class.forName()
            Class<?> aClass1 = Class.forName("com.kfm.base.reflect.Student");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        System.out.println(studentClass);

//        getClassInfo(aClass);

//        getConstructors(aClass);

//        getFields(aClass);

        getMehods(studentClass);
    }

    public static void getClassInfo(Class cla){
        // 2. 运行时获取类的信息(字段、方法、构造、父类、接口、注解、内部类、修饰符...)
        // 获取类名
        String name = cla.getName();
        System.out.println("getName:" + name);
        // 获取类名(简称)
        String simpleName = cla.getSimpleName();
        System.out.println("getSimpleName:" + simpleName);
        // 获取包名
        Package aPackage = cla.getPackage();
        System.out.println("getPackage:" + aPackage);
        // 修饰符
        int modifiers = cla.getModifiers();
        System.out.println("getModifiers: " + modifiers);
        System.out.println(Modifier.toString(modifiers));

        // 获取父类
        Class superclass = cla.getSuperclass();
        System.out.println("getSuperclass: " + superclass);
        // 实现的接口
        Class[] interfaces = cla.getInterfaces();
        System.out.println(Arrays.toString(interfaces));
    }


    public static void getConstructors(Class cla){
        // 3. 获取类的构造方法
        // 获取所有 public 修饰的构造方法
        Constructor[] constructors = cla.getConstructors();
        System.out.println(Arrays.toString(constructors));
        // 获取所有声明的构造方法
        Constructor[] declaredConstructors = cla.getDeclaredConstructors();
        System.out.println(Arrays.toString(declaredConstructors));
        try {
            // 获取指定参数类型的 public 构造方法
            Constructor constructor = cla.getConstructor(); // 无参构造
            Constructor constructor1 = cla.getConstructor(String.class, int.class); // 有参构造
//            System.out.println(constructor);
            Constructor declaredConstructor = cla.getDeclaredConstructor(String.class);
            System.out.println(declaredConstructor);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    public static void getFields(Class cla){
        // 4. 获取类的字段

        // 获取所有 public 修饰的字段(包含父类继承的 public 字段)
        Field[] fields = cla.getFields();
//        System.out.println(Arrays.toString(fields)); // id, pId

        // 获取所有声明的字段(不包含父类继承的字段)
        Field[] declaredFields = cla.getDeclaredFields();
//        System.out.println(Arrays.toString(declaredFields));

        try {
            // 获取指定名称的字段
            Field id = cla.getField("pId");
//            System.out.println(id);
            Field name = cla.getDeclaredField("name");
            System.out.println(name);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }

    }

    public static void getMehods(Class cla){
        // 5. 获取类的方法
        // 获取所有 public 修饰的方法(包含父类继承的 public 方法)
        Method[] methods = cla.getMethods();
//        System.out.println(Arrays.toString(methods));

        Method[] declaredMethods = cla.getDeclaredMethods();
//        System.out.println(Arrays.toString(declaredMethods));

        try {
            // 获取指定名称的方法
            Method show = cla.getMethod("show");
//            System.out.println(show);

            Method study = cla.getDeclaredMethod("study");
            System.out.println(study);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

class Person {
    private String pName;
    int pAge;

    protected String pGender;

    public int pId;

    public void pShow(){
        System.out.println("show");
    }

    private void pStudy(){
        System.out.println("study");
    }

    void pSay(){
        System.out.println("say");
    }
}

class Student extends Person implements Serializable, RandomAccess {
    private String name;
    int age;

    protected String gender;

    public int id;

    private Student(){}

    private Student(String name){
        this.name = name;
    }

    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }

    protected Student(String name, int age, String gender){

    }

    public void show(){
        System.out.println("show");
    }

    private void study(){
        System.out.println("study");
    }

    void say(){
        System.out.println("say");
    }

    public void test(){
        study();
        say();
        show();
        pShow();
        pSay();
//        finalize();
//        wait();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", id=" + id +
                "} " + super.toString();
    }
}


